package com.spark.gaea.quartz.utils;


import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.KeyMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Calendar;
import java.util.Date;

public class TimeTaskUtil {
	private static final Logger logger;
	private static Trigger trigger;
	private static SchedulerFactory schedFact;
	private static Scheduler scheduler;

	public static <T extends Job> boolean startTaskTime(final String taskPK, final String taskGroup, final T t,
			final TimeTask timeTask) {
		final boolean startNow = true;
		final JobDataMap dataMap = new JobDataMap();
		return startTaskTime(taskPK, taskGroup, t, dataMap, timeTask, startNow);
	}

	public static <T extends Job> boolean startTaskTime(final String taskPK, final String taskGroup, final T t,
			final JobDataMap dataMap, final TimeTask timeTask) {
		final boolean startNow = true;
		return startTaskTime(taskPK, taskGroup, t, dataMap, timeTask, startNow);
	}

	public static <T extends Job> boolean startTaskTime(final String taskPK, final String taskGroup, final T t,
			final TimeTask timeTask, final boolean startNow) {
		final JobDataMap dataMap = new JobDataMap();
		return startTaskTime(taskPK, taskGroup, t, dataMap, timeTask, startNow);
	}

	public static <T extends Job> boolean startTaskTime(final String taskPK, final String taskGroup, final T t,
			final JobDataMap dataMap, final TimeTask timeTask, final boolean startNow) {
		final boolean status = timeTask.isStatus();
		if (status) {
			stopTaskTime(taskPK, taskGroup);
			if (startNow) {
				setTriggerOnstartNow(taskPK, taskGroup, timeTask);
			} else {
				final Calendar cal = Calendar.getInstance();
				cal.add(12, -5);
				System.out.println("5\u5206\u949f\u4e4b\u524d\u7684\u65f6\u95f4" + cal.getTime());
				setTriggerOnstartAt(taskPK, taskGroup, timeTask, cal.getTime());
			}
			final JobDetail job = JobBuilder.newJob(t.getClass()).withIdentity(taskPK, taskGroup).setJobData(dataMap)
					.build();
			try {
				TimeTaskUtil.scheduler = StdSchedulerFactory.getDefaultScheduler();
				if (timeTask.isListenerStatus()) {
					final TriggerListener myTriggerListener = new MonitorTriggerListener();
					final KeyMatcher<TriggerKey> tkeyMatcher = KeyMatcher.keyEquals(TimeTaskUtil.trigger.getKey());
					TimeTaskUtil.scheduler.getListenerManager().addTriggerListener(myTriggerListener, tkeyMatcher);
				}
				TimeTaskUtil.scheduler.scheduleJob(job, TimeTaskUtil.trigger);
				TimeTaskUtil.scheduler.start();
				return true;
			} catch (SchedulerException e) {
				TimeTaskUtil.logger.error(e.getMessage());
				e.printStackTrace();
			}
		}
		return false;
	}

	public static boolean stopTaskTime(final String taskPK, final String taskGroup) {
		try {
			TimeTaskUtil.scheduler = TimeTaskUtil.schedFact.getScheduler();
			if (TimeTaskUtil.scheduler != null) {
				TimeTaskUtil.scheduler.pauseTrigger(TriggerKey.triggerKey(taskPK, taskGroup));
				TimeTaskUtil.scheduler.unscheduleJob(TriggerKey.triggerKey(taskPK, taskGroup));
				TimeTaskUtil.scheduler.deleteJob(JobKey.jobKey(taskPK, taskGroup));
			}
			return true;
		} catch (SchedulerException e) {
			TimeTaskUtil.logger.error(e.getMessage());
			e.printStackTrace();
			return false;
		}
	}

	private static void setTriggerOnstartNow(final String taskPK, final String taskGroup, final TimeTask timeTask) {
		if ("01".equals(timeTask.getType())) {
			CronScheduleBuilder cronScheduleBuilder = null;
			if (TimeTask.TaskTimeType.DayPlan.equals(timeTask.getTaskTimeType())) {
				cronScheduleBuilder = CronScheduleBuilder
						.dailyAtHourAndMinute(timeTask.getHour(), timeTask.getMinute());
			}
			if (TimeTask.TaskTimeType.WeekPlan.equals(timeTask.getTaskTimeType())) {
				cronScheduleBuilder = CronScheduleBuilder
						.weeklyOnDayAndHourAndMinute(timeTask.getWeek(), timeTask.getHour(), timeTask.getMinute());
			}
			if (TimeTask.TaskTimeType.MonthlyPlan.equals(timeTask.getTaskTimeType())) {
				cronScheduleBuilder = CronScheduleBuilder
						.monthlyOnDayAndHourAndMinute(timeTask.getDay(), timeTask.getHour(), timeTask.getMinute());
			}
			TimeTaskUtil.trigger = TriggerBuilder.newTrigger().withIdentity(taskPK, taskGroup).startNow()
					.withSchedule((ScheduleBuilder) cronScheduleBuilder).build();
		}
		if (TimeTask.TaskTimeType.Frequency.equals(timeTask.getTaskTimeType())) {
			if (timeTask.getRepeatNumber() <= 0) {
				TimeTaskUtil.trigger = TriggerBuilder.newTrigger().withIdentity(taskPK, taskGroup).startNow()
						.withSchedule((ScheduleBuilder) SimpleScheduleBuilder.simpleSchedule()
								.withIntervalInSeconds(timeTask.getSecond()).repeatForever()).build();
			} else {
				TimeTaskUtil.trigger = TriggerBuilder.newTrigger().withIdentity(taskPK, taskGroup).startNow()
						.withSchedule((ScheduleBuilder) SimpleScheduleBuilder.simpleSchedule()
								.withIntervalInSeconds(timeTask.getSecond())
								.withRepeatCount(timeTask.getRepeatNumber())).build();
			}
		}
		if (TimeTask.TaskTimeType.CronExpression.equals(timeTask.getTaskTimeType())) {
			TimeTaskUtil.trigger = TriggerBuilder.newTrigger().withIdentity(taskPK, taskGroup).startNow()
					.withSchedule((ScheduleBuilder) CronScheduleBuilder.cronSchedule(timeTask.getCronStr())).build();
		}
	}

	private static void setTriggerOnstartAt(final String taskPK, final String taskGroup, final TimeTask timeTask,
			final Date startTime) {
		if ("01".equals(timeTask.getType())) {
			CronScheduleBuilder cronScheduleBuilder = null;
			if (TimeTask.TaskTimeType.DayPlan.equals(timeTask.getTaskTimeType())) {
				cronScheduleBuilder = CronScheduleBuilder
						.dailyAtHourAndMinute(timeTask.getHour(), timeTask.getMinute());
			}
			if (TimeTask.TaskTimeType.WeekPlan.equals(timeTask.getTaskTimeType())) {
				cronScheduleBuilder = CronScheduleBuilder
						.weeklyOnDayAndHourAndMinute(timeTask.getWeek(), timeTask.getHour(), timeTask.getMinute());
			}
			if (TimeTask.TaskTimeType.MonthlyPlan.equals(timeTask.getTaskTimeType())) {
				cronScheduleBuilder = CronScheduleBuilder
						.monthlyOnDayAndHourAndMinute(timeTask.getDay(), timeTask.getHour(), timeTask.getMinute());
			}
			TimeTaskUtil.trigger = TriggerBuilder.newTrigger().withIdentity(taskPK, taskGroup).startAt(startTime)
					.withSchedule((ScheduleBuilder) cronScheduleBuilder).build();
		}
		if (TimeTask.TaskTimeType.Frequency.equals(timeTask.getTaskTimeType())) {
			if (timeTask.getRepeatNumber() <= 0) {
				TimeTaskUtil.trigger = TriggerBuilder.newTrigger().withIdentity(taskPK, taskGroup).startAt(startTime)
						.withSchedule((ScheduleBuilder) SimpleScheduleBuilder.simpleSchedule()
								.withIntervalInSeconds(timeTask.getSecond()).repeatForever()).build();
			} else {
				TimeTaskUtil.trigger = TriggerBuilder.newTrigger().withIdentity(taskPK, taskGroup).startAt(startTime)
						.withSchedule((ScheduleBuilder) SimpleScheduleBuilder.simpleSchedule()
								.withIntervalInSeconds(timeTask.getSecond())
								.withRepeatCount(timeTask.getRepeatNumber())).build();
			}
		}
		if (TimeTask.TaskTimeType.CronExpression.equals(timeTask.getTaskTimeType())) {
			TimeTaskUtil.trigger = TriggerBuilder.newTrigger().withIdentity(taskPK, taskGroup).startAt(startTime)
					.withSchedule((ScheduleBuilder) CronScheduleBuilder.cronSchedule(timeTask.getCronStr())).build();
		}
	}

	static {
		logger = LoggerFactory.getLogger(TimeTaskUtil.class);
		TimeTaskUtil.trigger = null;
		TimeTaskUtil.schedFact = new StdSchedulerFactory();
		TimeTaskUtil.scheduler = null;
	}
}
